package org.rcy.framework.mq.config.amqp;

import org.rcy.framework.api.mq.AbstractMessage;
import org.rcy.framework.mq.converter.RabbitMqMessageConverter;
import org.rcy.framework.mq.listener.RabbitMessageListenerRegistrarPostProcessor;
import org.rcy.framework.mq.listener.RabbitMqMessageListenerRegistrar;
import org.rcy.framework.mq.producer.MessageProducer;
import org.rcy.framework.mq.producer.RabbitMQProducer;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionNameStrategy;
import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.amqp.rabbit.core.RabbitOperations;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;

import java.time.Duration;


/**
 * @author 吴康桥
 * @Description
 * @date 2022/11/11 17:46
 */

@Configuration
@EnableConfigurationProperties({RabbitProperties.class})
@ConditionalOnProperty({"spring.rabbitmq.host"})
public class SpringAMQPAutoConfiguration {
	@Autowired
	RabbitProperties properties;

	public SpringAMQPAutoConfiguration() {
	}

	@Bean
	public ConnectionFactory connectionFactory() {
		com.rabbitmq.client.ConnectionFactory factory = new com.rabbitmq.client.ConnectionFactory();
		factory.setHost(this.properties.getHost());
		factory.setUsername(this.properties.getUsername());
		factory.setPassword(this.properties.getPassword());
		factory.setVirtualHost(this.properties.getVirtualHost());
		factory.setAutomaticRecoveryEnabled(false);
		factory.setNetworkRecoveryInterval(10000);
		factory.setRequestedHeartbeat(2);
		CachingConnectionFactory connectionFactory = new CachingConnectionFactory(factory);
		return connectionFactory;
	}

	@Bean
	public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
		RabbitTemplate template = new RabbitTemplate(connectionFactory);
		template.setMessageConverter(messageConverter);
		return template;
	}

	@Bean
	public MessageConverter messageConverter() {return new RabbitMqMessageConverter();}

	@Bean
	public RabbitAdmin admin(ConnectionFactory connectionFactory) {
		return new RabbitAdmin(connectionFactory);
	}

	@Bean
	@Primary
	public <M extends AbstractMessage> MessageProducer<M> producer(RabbitTemplate rabbitTemplate, RabbitAdmin admin) {
		return new RabbitMQProducer<>(rabbitTemplate, admin);
	}
	@Primary
	@Bean(
			name = {"rabbitMessageListenerRegistrar"}
	)
	public RabbitMqMessageListenerRegistrar rabbitMessageListenerRegistrar() {
			return new RabbitMqMessageListenerRegistrar();
	}
	@Bean
	@DependsOn({"rabbitMessageListenerRegistrar"})
	public RabbitMessageListenerRegistrarPostProcessor messageListenerRegisterPostProcessor() {
			return new RabbitMessageListenerRegistrarPostProcessor();
	}
}
